This is one page of the R Handbook for Epidemiologists, but is being printed as a stand-alone page.
You can find the complete handbook on Github
Data visualisation is increasingly required to be interrogable by the audience. Consequently creating interactive plots are becoming common. There are several ways to include these but the two most important are {plotly} and {shiny}.
{Shiny} is covered in another part of this handbook, so we will only cover {plotly} here. #TODO - link to shiny page
Making plots interactive can sound more difficult than it turns out to be, thanks to some fantastic tools.
In this section, you’ll learn to easily make a plot interactive with {the wonders {ggplot2} and {plotly}
In the example you saw a very basic epicurve that had been transformed to bbe interactive using the fantastic {ggplot2} - {plotly} integrations. So to start, make a basic chart of your own:
Loading data
Manipulate and add columns (best taught in the epicurves section)
linelist <- linelist %>%
dplyr::mutate(
## If the outcome column is NA, change to "Unknown"
outcome = dplyr::if_else(condition = is.na(outcome),
true = "Unknown",
false = outcome),
## If the date of infection is NA, use the date of onset instead
date_earliest = dplyr::if_else(condition = is.na(date_infection),
true = date_onset,
false = date_infection),
## Summarise earliest date to earliest week
week_earliest = lubridate::floor_date(x = date_earliest,
unit = "week",
week_start = 1)
)Count for plotting
Make into a plot
p <- linelist %>%
ggplot()+
geom_col(aes(week_earliest, n, fill = outcome))+
xlab("Week of infection/onset") + ylab("Cases per week")+
theme_minimal()Make interactive
Voila!
When exporting in an Rmarkdown generated HTML (like this book!) you want to make the plot as small as possible (with no negative side effects in most cases). For this, just add add this line:
Some of the buttons on a standard plotly (as shown on the preparation tab) are superfluous and can be distracting, so it’s best to remove them. You can do this simply by piping the output into plotly::config
## these buttons are superfluous/distracting
plotly_buttons_remove <- list('zoom2d','pan2d','lasso2d', 'select2d','zoomIn2d',
'zoomOut2d','autoScale2d','hoverClosestCartesian',
'toggleSpikelines','hoverCompareCartesian')
p <- p %>%
plotly::config(displaylogo = FALSE, modeBarButtonsToRemove = plotly_buttons_remove)Earlier you saw #TODO link to heatmaps how to make heatmaps, and they are just as easy to make interactive.
You can even make interactive maps! However, they’re slightly trickier. Although {plotly} works well with ggplot2::geom_sf in RStudio, when you try to include it’s outputs in Rmarkdown HTML files (like this book), it doesn’t work well.
So instead you can use {plotly}’s own mapping tools which can be tricky but are easy when you know how. Read on…
We’re going to use Covid-19 incidence across African countries for this example. The data used can be found on the World Health Organisation website.
You’ll also need a new type of file, a GeoJSON, which is sort of similar to a shp file for those familiar with GIS. For this book, we used one from here.
GeoJSON files are stored in R as complex lists and you’ll need to maipulate them a little.
## You need two new packages: {rjson} and {purrr}
pacman::p_load(plotly, rjson, purrr)
## This is a simplified version of the WHO data
df <- rio::import(here::here("data", "covid_incidence.csv"))
## Load your geojson file
geoJSON <- rjson::fromJSON(file=here::here("data", "africa_countries.geo.json"))
## Here are some of the properties for each element of the object
head(geoJSON$features[[1]]$properties)
## $scalerank
## [1] 1
##
## $featurecla
## [1] "Admin-0 country"
##
## $labelrank
## [1] 6
##
## $sovereignt
## [1] "Burundi"
##
## $sov_a3
## [1] "BDI"
##
## $adm0_dif
## [1] 0This is the tricky part. For {plotly} to match your incidence data to GeoJSON, the countries in the geoJSON need an id in a specific place in the list of lists. For this we need to build a basic function:
## The property column we need to choose here is "sovereignt" as it is the names for each country
give_id <- function(x){
x$id <- x$properties$sovereignt ## Take sovereignt from properties and set it as the id
return(x)
}
## Use {purrr} to apply this function to every element of the features list of the geoJSON object
geoJSON$features <- purrr::map(.x = geoJSON$features, give_id)plotly::plot_ly() %>%
plotly::add_trace( #The main plot mapping functionn
type="choropleth",
geojson=geoJSON,
locations=df$Name, #The column with the names (must match id)
z=df$Cumulative_incidence, #The column with the incidence values
zmin=0,
zmax=57008,
colorscale="Viridis",
marker=list(line=list(width=0))
) %>%
plotly::colorbar(title = "Cases per million") %>%
plotly::layout(title = "Covid-19 cumulative incidence",
geo = list(scope = 'africa')) %>%
plotly::config(displaylogo = FALSE, modeBarButtonsToRemove = plotly_buttons_remove)Plotly is not just for R, but also works well with Python (and really any data science language as it’s built in JavaScript). You can read more about it on the plotly website